# -*- coding: utf-8 -*-
import pandas as pd
from .event import Event, EVENT
from .models import MarketOrder, LimitOrder
from .logger import get_logger

# 策略类
class Strategy(object):
    # 初始化函数, 获得数据引擎, context等
    def __init__(self, event_hub, context):
        self.event_hub = event_hub
        self.context = context
        self._signal_list = []
        self.datetime = None
        self.event = None

    def before_trading(self, context):
        # 用户继承该类, 然后覆写用
        pass

    def handle_bar(self, context, bar_dict):
        # 用户继承该类, 然后覆写用
        pass

    def rebalance(self, context):
        # 目前没用了
        pass

    def after_trading(self, context):
        # 用户继承该类, 然后覆写用
        pass

    # 下单. 默认市价单. symbol为股票, amount为股数
    def order_shares(self, symbol, amount, style=MarketOrder()):
        if self.context.data_handler.check_stop(symbol):
            get_logger().warn("reject: " + symbol + " is stoped now!")
            return
        if amount == 0:
            get_logger().info("amount = 0, ignore")
            return
        get_logger().debug("new generated signal: " + symbol + "  " + str(amount) + " " + style.info())

        if amount * self.event.bar_dict[symbol].close > self.context.portfolio.current_holdings['cash']:
            get_logger().info("order: " + symbol + " " + str(amount) +
                              "rejected : money is not enough")
            return

        if amount + self.context.portfolio.current_positions[symbol] < 0:
            get_logger().info("order: " + symbol + " " + str(amount) +
                              "rejected : positions is not enough")
            return

        self.event_hub.publish_event(Event(EVENT.PENDING_ORDER, symbol=symbol, amount=amount, datetime=self.context.now,
                                           style=style, signal_type='ORDER'))

    # 下单, 单位是手数. 1手=100股
    def order_lots(self, symbol, amount, style=MarketOrder()):
        # amount 代表手数, 一手 = 100股
        if self.context.data_handler.check_stop(symbol):
            get_logger().warn("reject: " + symbol + " is stoped now!")
            return
        self.order_shares(symbol, amount*100.0, style)

    def order_value(self, symbol, value, style=MarketOrder()):
        # 买入或卖出一定价格的股票, 股票按照100股的整数倍买入, 不考虑手续费
        if self.context.data_handler.check_stop(symbol):
            get_logger().warn("reject: " + symbol + " is stoped now!")
            return
        value = float(value)
        if value > 0:
            value = min(value, self.context.portfolio.current_holdings['cash'])
        direction = 1 if value > 0 else -1
        price = self.event.bar_dict[symbol].close
        amount = abs(value) // (price*100) * 100
        self.order_shares(symbol, amount * direction, style)

    # 下单当前所有资金percent百分比的钱的股票
    def order_percent(self, symbol, percent, style=MarketOrder()):
        if percent > 1 or percent < 0:
            get_logger().warn("percent must between 0 and 1")
            return
        if self.context.data_handler.check_stop(symbol):
            get_logger().warn("reject: " + symbol + " is stoped now!")
            return
        # current_holdings['total'] 和 all_holdings[-1]['total'] 暂时不一致
        value = self.context.portfolio.all_holdings[-1]['total'] * percent
        self.order_value(symbol, value, style)

    def order_target_value(self, symbol, cash_amount, style=MarketOrder()):
        # 买入股票, 直至股票价值等值于cash_amount
        if self.context.data_handler.check_stop(symbol):
            get_logger().warn("reject: " + symbol + " is stoped now!")
            return
        current_cash = self.context.portfolio.current_holdings[symbol]
        delta_cash = cash_amount - current_cash
        self.order_value(symbol, delta_cash, style)

    def order_target_percent(self, symbol, percent, style=MarketOrder()):
        # 买入股票到投资组合资金的百分比
        # 投资组合现金 = 空闲资金 + 已经持有的该股票可以按照市场价换算的资金

        if percent > 1 or percent < 0:
            get_logger().warn("percent must between 0 and 1")
            return
        if self.context.data_handler.check_stop(symbol):
            get_logger().warn("reject: " + symbol + " is stoped now!")
            return
        price = self.event.bar_dict[symbol].close
        current_cash = self.context.portfolio.current_positions[symbol] * price
        target_cash = self.context.portfolio.all_holdings[-1]['total'] * percent
        delta_cash =target_cash - current_cash
        self.order_value(symbol, delta_cash, style)

    def _prepare(self, event):
        # 运行策略之前的初始化
        self._signal_list = []
        self.event = event
        self.datetime = event.now

    def handle_bar_event(self, event):
        # bar event的处理函数
        self._prepare(event)
        self.handle_bar(event.context, event.bar_dict)

    def before_bar_event(self, event):
        # before_bar_event的处理函数
        self.before_trading(event.context)

    def after_bar_event(self, event):
        # after_bar_event的处理函数
        self.after_trading(event.context)